package weaviate

import (
	"context"
	"fmt"
	"time"

	"github.com/testcontainers/testcontainers-go"
	"github.com/testcontainers/testcontainers-go/wait"
)

const (
	httpPort = "8080/tcp"
	grpcPort = "50051/tcp"
)

// WeaviateContainer represents the Weaviate container type used in the module
type WeaviateContainer struct {
	testcontainers.Container
}

// Deprecated: use Run instead
// RunContainer creates an instance of the Weaviate container type
func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*WeaviateContainer, error) {
	return Run(ctx, "semitechnologies/weaviate:1.29.0", opts...)
}

// Run creates an instance of the Weaviate container type
func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*WeaviateContainer, error) {
	moduleOpts := []testcontainers.ContainerCustomizer{
		testcontainers.WithCmd("--host", "0.0.0.0", "--scheme", "http", "--port", "8080"),
		testcontainers.WithExposedPorts(httpPort, grpcPort),
		testcontainers.WithEnv(map[string]string{
			"AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED": "true",
			"PERSISTENCE_DATA_PATH":                   "/var/lib/weaviate",
		}),
		testcontainers.WithWaitStrategy(
			wait.ForListeningPort(httpPort).WithStartupTimeout(5*time.Second),
			wait.ForListeningPort(grpcPort).WithStartupTimeout(5*time.Second),
			wait.ForHTTP("/v1/.well-known/ready").WithPort(httpPort),
		),
	}

	ctr, err := testcontainers.Run(ctx, img, append(moduleOpts, opts...)...)
	var c *WeaviateContainer
	if ctr != nil {
		c = &WeaviateContainer{Container: ctr}
	}

	if err != nil {
		return c, fmt.Errorf("run weaviate: %w", err)
	}

	return c, nil
}

// HttpHostAddress returns the schema and host of the Weaviate container.
// At the moment, it only supports the http scheme.
//
//nolint:revive,staticcheck //FIXME
func (c *WeaviateContainer) HttpHostAddress(ctx context.Context) (string, string, error) {
	endpoint, err := c.PortEndpoint(ctx, httpPort, "")
	if err != nil {
		return "", "", fmt.Errorf("port endpoint: %w", err)
	}

	return "http", endpoint, nil
}

// GrpcHostAddress returns the gRPC host of the Weaviate container.
// At the moment, it only supports unsecured gRPC connection.
func (c *WeaviateContainer) GrpcHostAddress(ctx context.Context) (string, error) {
	return c.PortEndpoint(ctx, grpcPort, "")
}
